package com.cysd.ewmxns.sdw_utils;

import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Looper;

import com.tencent.mmkv.MMKV;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

public class SpUtils {
    private volatile static SpUtils mInstance;
    private SharedPreferences mPref = MMKV.defaultMMKV();
    private Handler mHandler = new Handler(Looper.getMainLooper());
    private Set<String> mTimeoutKeys = new HashSet<>();
    private static final long DEFAULT_TIMEOUT = TimeUnit.HOURS.toMillis(24); // 默认24小时超时
    private SpUtils(){
        startTimeoutChecker();
    }

    /**
     *          单例模式
     * @return
     */
    public static SpUtils getInstance(){
        if (mInstance == null){
            synchronized (SpUtils.class){
                if (mInstance == null){
                    mInstance = new SpUtils();
                }
            }
        }
        return mInstance;
    }


    public void putString(String key,String value){
        SharedPreferences.Editor editor = mPref.edit();
        editor.putString(key,value);
        editor.commit();
    }

    public void putLong(String key,long value){
        SharedPreferences.Editor editor = mPref.edit();
        editor.putLong(key,value);
        editor.commit();
    }
    public void putInt(String key,int value){
        SharedPreferences.Editor editor = mPref.edit();
        editor.putInt(key,value);
        editor.commit();
    }

    public void putFloat(String key,float value){
        SharedPreferences.Editor editor = mPref.edit();
        editor.putFloat(key,value);
        editor.commit();
    }

    public void putBoolean(String key,boolean value){
        SharedPreferences.Editor editor = mPref.edit();
        editor.putBoolean(key,value);
        editor.commit();
    }

    public String getString(String key){
        return mPref.getString(key,"");
    }

    public String getString(String key,String value){
        return mPref.getString(key,value);
    }

    public long getLong(String key){
        return mPref.getLong(key,0);
    }

    public long getLong(String key,long value){
        return mPref.getLong(key,value);
    }

    public int getInt(String key){
        return mPref.getInt(key,0);
    }

    public int getInt(String key,int value){
        return mPref.getInt(key,value);
    }

    public float getFloat(String key){
        return mPref.getFloat(key,0);
    }

    public float getFloat(String key,float value){
        return mPref.getFloat(key,value);
    }

    public Boolean getBoolean(String key){
        return mPref.getBoolean(key,false);
    }

    public Boolean getBoolean(String key,boolean value){
        return mPref.getBoolean(key,value);
    }


    /**
     *          根据key清除value的缓存
     * @param key
     */
    public void remove(String key){
        SharedPreferences.Editor editor = mPref.edit();
        editor.remove(key);
        editor.commit();
    }
    /**
     *          清除所有数据缓存
     */
    public void clear(){
        SharedPreferences.Editor editor = mPref.edit();
        editor.clear();
        editor.commit();
    }


    // ==================== 新增超时相关方法 ====================

    /**
     * 设置带超时时间的boolean值
     * @param key 存储的key
     * @param value 要存储的值
     * @param timeoutMillis 超时时间(毫秒)
     */
    public void putBooleanWithTimeout(String key, boolean value, long timeoutMillis) {
        if (value) {
            // 只有设置为true时才记录时间
            putLong(getTimeKey(key), System.currentTimeMillis());
            putLong(getTimeoutKey(key), timeoutMillis);
            // 添加到监听集合
            mTimeoutKeys.add(key);
        } else {
            // 设置为false时移除时间记录
            remove(getTimeKey(key));
            remove(getTimeoutKey(key));
            // 从监听集合中移除
            mTimeoutKeys.remove(key);
        }
        putBoolean(key, value);
    }

    /**
     * 设置boolean值，使用默认超时时间(24小时)
     * @param key 存储的key
     * @param value 要存储的值
     */
    public void putBooleanWithTimeout(String key, boolean value) {
        putBooleanWithTimeout(key, value, DEFAULT_TIMEOUT);
    }

    /**
     * 获取boolean值，并自动检查是否超时
     * @param key 存储的key
     * @return 如果超时则返回false，否则返回存储的值
     */
    public boolean getBooleanWithTimeoutCheck(String key) {
        if (!mTimeoutKeys.contains(key)) {
            return getBoolean(key, false);
        }

        long savedTime = getLong(getTimeKey(key), 0);
        long timeout = getLong(getTimeoutKey(key), DEFAULT_TIMEOUT);

        if (System.currentTimeMillis() - savedTime > timeout) {
            // 超时后自动重置为false
            putBoolean(key, false);
            remove(getTimeKey(key));
            remove(getTimeoutKey(key));
            mTimeoutKeys.remove(key);
            return false;
        }

        return getBoolean(key, false);
    }

    /**
     * 手动移除某个key的超时检查
     * @param key 要移除的key
     */
    public void removeTimeoutCheck(String key) {
        remove(getTimeKey(key));
        remove(getTimeoutKey(key));
        mTimeoutKeys.remove(key);
    }

    // ==================== 私有方法 ====================

    private String getTimeKey(String key) {
        return key + "_time";
    }

    private String getTimeoutKey(String key) {
        return key + "_timeout";
    }

    private void startTimeoutChecker() {
        // 每5分钟检查一次超时
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                checkAllTimeouts();
                // 继续下一次检查
                mHandler.postDelayed(this, TimeUnit.MINUTES.toMillis(5));
            }
        }, TimeUnit.MINUTES.toMillis(5));
    }

    private void checkAllTimeouts() {
        // 使用副本遍历，避免并发修改异常
        Set<String> keys = new HashSet<>(mTimeoutKeys);
        for (String key : keys) {
            getBooleanWithTimeoutCheck(key);
        }
    }
}
